package org.torreya.etange;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Queue;
import java.util.concurrent.SynchronousQueue;

public class Etange {

	private DataSource source;
	private int max;
	private int min;
	private int count;
	private Queue<Connection> freeConnPool;
	private Queue<Connection> usedConnPool;

	/**
	 * constructor method
	 * 
	 * @param max
	 * @param min
	 */
	protected Etange(final DataSource source, int max, int min) {
		super();
		this.source = source;
		this.max = max;
		this.min = min;
		this.count = 0;

	}

	/**
	 * 
	 * @throws Exception
	 */
	public synchronized void init() throws Exception {
		// if free pool not been initialized ,then initialized
		if (freeConnPool == null)
			freeConnPool = new SynchronousQueue<Connection>();
		// if used pool not been initialized ,then initialized
		if (usedConnPool == null)
			usedConnPool = new SynchronousQueue<Connection>();
		// initialized free pool,put free connections
		if (freeConnPool.size() < min)
			for (int i = 0; i < min; i++)
				freeConnPool.add(source.createConnection());
		count = min;
	}

	/**
	 * get connection
	 * 
	 * @return connection
	 * @throws Exception
	 */
	public synchronized Connection getConnection() throws Exception {
		Connection connection = null;
		// if free connections is not empty
		if (freeConnPool.size() > 0) {
			connection = freeConnPool.poll();
			usedConnPool.add(connection);
		}
		// if free connections is empty
		if (freeConnPool.size() == 0) {
			if (usedConnPool.size() < max) {
				connection = source.createConnection();
				usedConnPool.add(connection);
				count++;
			}
		}
		return connection;

	}

	/**
	 * free connection
	 * 
	 * @param connection
	 */
	public synchronized void freeConnection(Connection connection) {
		usedConnPool.remove(connection);
		freeConnPool.add(connection);
	}

	/**
	 * release pool
	 * 
	 * @throws SQLException
	 */
	public synchronized void release() throws SQLException {
		if (usedConnPool.size() > 0) {
			usedConnPool.poll().close();
		}
		if (freeConnPool.size() > 0) {
			freeConnPool.poll().close();
		}
		count = 0;
	}

	/**
	 * @return the source
	 */
	public DataSource getSource() {
		return source;
	}

	/**
	 * @return the max
	 */
	public int getMax() {
		return max;
	}

	/**
	 * @return the min
	 */
	public int getMin() {
		return min;
	}

	/**
	 * @return the count
	 */
	public int getCount() {
		return count;
	}

}
